import CryptoJS from 'crypto-js'; // 确保安装了 crypto-js 库
import { get } from 'lodash'
function callWxSdkMethod(method, args) {
    return new Promise((resolve, reject) => {
        // 添加 success 和 fail 回调
        args.success = (res) => {
            resolve(res); // 调用成功时解析 Promise
        };
        args.fail = (err) => {
            reject(err); // 调用失败时拒绝 Promise
        };
        // 调用 wx_sdk 的方法
        get(jWeixin, method)(args);
    });
}

const apiList = [
    'updateAppMessageShareData',
    'updateTimelineShareData',
    'onMenuShareWeibo',
    'onMenuShareQZone',
    'startRecord',
    'stopRecord',
    'onVoiceRecordEnd',
    'playVoice',
    'pauseVoice',
    'stopVoice',
    'onVoicePlayEnd',
    'uploadVoice',
    'downloadVoice',
    'chooseImage',
    'previewImage',
    'uploadImage',
    'downloadImage',
    'translateVoice',
    'getNetworkType',
    'openLocation',
    'getLocation',
    'hideOptionMenu',
    'showOptionMenu',
    'hideMenuItems',
    'showMenuItems',
    'hideAllNonBaseMenuItem',
    'showAllNonBaseMenuItem',
    'closeWindow',
    'scanQRCode',
    'openProductSpecificView',
    'addCard',
    'chooseCard',
    'openCard'
]

class WeChatSDK {
    static appId = null;
    /**
     * WeChatSDK 构造函数
     * @param {Object} options - 初始化参数
     * @param {string} options.ticket - 从服务端获取的 isapi_ticket (必填)
     */
    constructor(ticket) {
        this.ticket = ticket; // isapi_ticket
        this.url = window.location.href; // 动态获取当前页面的 URL
        this.nonceStr = this.generateNonceStr(); // 随机生成 nonceStr
        this.timestamp = Math.floor(Date.now() / 1000); // 当前时间戳
        this.signature = this.generateSignature(); // 生成 signature
        this.isReady = false;
        this.queue = []; // 存储待执行的 API 调用

    }

    /**
     * 生成指定长度的随机字符串
     * @param {number} length - 随机字符串的长度 (非必填，默认值为 16)
     * @returns {string} - 生成的随机字符串
     */
    generateNonceStr(length = 16) {
        const chars = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789';
        let result = '';
        for (let i = 0; i < length; i++) {
            result += chars.charAt(Math.floor(Math.random() * chars.length));
        }
        return result;
    }

    /**
     * 生成签名
     * @returns {string} - 生成的签名
     */
    generateSignature() {
        const stringToSign = `jsapi_ticket=${this.ticket}&noncestr=${this.nonceStr}&timestamp=${this.timestamp}&url=${this.url}`;
        return CryptoJS.SHA1(stringToSign).toString(CryptoJS.enc.Hex);
    }
    /**
     * 初始化微信 JS-SDK
     * @returns {Promise} - 初始化结果
     */
    init() {
        if (typeof wx === 'undefined') {
            reject('wx object is not available. Please ensure the WeChat JS-SDK is loaded.');
            return;
        }
        return new Promise((resolve, reject) => {

            jWeixin.config({
                debug: false, // 开启调试模式
                appId: WeChatSDK.appId,
                timestamp: this.timestamp,
                nonceStr: this.nonceStr,
                signature: this.signature,
                openTagList: [
                    'wx-open-launch-weapp',
                    'wx-open-launch-app',
                    'wx-open-subscribe',
                    'wx-open-audio'
                ],
                jsApiList: apiList
            })



            jWeixin.ready(() => {
                this.isReady = true;
                this.processQueue(); // 处理队列中的 API 调用
                resolve('WeChat JS-SDK is ready');
            });

            jWeixin.error((err) => {
                this.isReady = false;
                reject(`WeChat JS-SDK initialization failed: ${err}`);
            });
        });
    }

    // 处理队列中的 API 调用
    processQueue() {
        while (this.queue.length > 0) {
            const { method, args, resolve, reject } = this.queue.shift();
            this[method](...args).then(resolve).catch(reject);
        }
    }

    /**
     * 调用 API 的通用方法
     * @param {string} method - 方法名
     * @param {Object} args - 方法参数
     * @returns {Promise}
     */
    callApi(method, args) {
        return new Promise((resolve, reject) => {
            if (this.isReady) {
                callWxSdkMethod(method, args).then(resolve).catch(reject);
            } else {
                // 如果 SDK 尚未准备好，将调用添加到队列
                this.queue.push({ method, args, resolve, reject });
            }
        });
    }

    static setAppId(appId) {
        WeChatSDK.appId = appId; // 设置静态 appId
    }

    /**
     * 销毁 WeChatSDK 实例
     */
    destroy() {
        this.isReady = false; // 重置状态
        this.queue = []; // 清空队列
        // 其他需要清理的资源可以在这里添加
        console.log('WeChatSDK instance has been destroyed.');
    }

    // 小程序方法
    navigateTo(args) {
        if (jWeixin.miniProgram) {
            this.callApi('miniProgram.navigateTo', args)
        }
    }

    navigateBack(args) {
        if (jWeixin.miniProgram) {
            this.callApi('miniProgram.navigateBack', args)
        }
    }

    switchTab(args) {
        if (jWeixin.miniProgram) {
            this.callApi('miniProgram.switchTab', args)
        }
    }

    reLaunch(args) {
        if (jWeixin.miniProgram) {
            this.callApi('miniProgram.reLaunch', args)
        }
    }


    redirectTo(args) {
        if (jWeixin.miniProgram) {
            this.callApi('miniProgram.redirectTo', args)
        }
    }

    postMessage(args) {
        if (jWeixin.miniProgram) {
            this.callApi('miniProgram.postMessage', args)
        }
    }

    getEnv(args) {
        if (jWeixin.miniProgram) {
            this.callApi('miniProgram.getEnv', args)
        }
    }

    /**
     * 更新应用分享数据
     * @param {Object} args - 分享数据参数
     * @param {string} args.title - 分享标题
     * @param {string} args.desc - 分享描述
     * @param {string} args.link - 分享链接
     * @param {string} args.imgUrl - 分享图标
     */
    updateAppMessageShareData(args) {
        // 实现更新应用分享数据的逻辑

        return this.callApi('updateAppMessageShareData', args)
    }

    /**
     * 更新时间线分享数据
     * @param {Object} args - 分享数据参数
     * @param {string} args.title - 分享标题
     * @param {string} args.link - 分享链接
     * @param {string} args.imgUrl - 分享图标
     */
    updateTimelineShareData(args) {
        // 实现更新时间线分享数据的逻辑

        return this.callApi('updateTimelineShareData', args)
    }

    /**
     * 分享到微博
     * @param {Object} args - 分享参数
     * @param {string} args.title - 分享标题
     * @param {string} args.link - 分享链接
     */
    onMenuShareWeibo(args) {
        // 实现分享到微博的逻辑
        return this.callApi('onMenuShareWeibo', args)
    }

    /**
     * 分享到 QQ 空间
     * @param {Object} args - 分享参数
     * @param {string} args.title - 分享标题
     * @param {string} args.link - 分享链接
     */
    onMenuShareQZone(args) {
        // 实现分享到 QQ 空间的逻辑
        return this.callApi('onMenuShareQZone', args)
    }

    /**
     * 开始录音
     * @param {Object} args - 录音参数
     */
    startRecord(args) {
        // 实现开始录音的逻辑
        return this.callApi('startRecord', args)
    }

    /**
     * 停止录音
     * @param {Object} args - 停止录音参数
     */
    stopRecord(args) {
        // 实现停止录音的逻辑
        return this.callApi('stopRecord', args)
    }

    /**
     * 语音录音结束
     * @param {Object} args - 语音录音结束参数
     */
    onVoiceRecordEnd(args) {
        // 实现语音录音结束的逻辑
        return this.callApi('onVoiceRecordEnd', args)
    }

    /**
     * 播放语音
     * @param {Object} args - 播放语音参数
     * @param {string} args.localId - 需要播放的语音的 ID
     */
    playVoice(args) {
        // 实现播放语音的逻辑
        return this.callApi('playVoice', args)
    }

    /**
     * 暂停语音
     * @param {Object} args - 暂停语音参数
     */
    pauseVoice(args) {
        // 实现暂停语音的逻辑
        return this.callApi('pauseVoice', args)
    }

    /**
     * 停止语音
     * @param {Object} args - 停止语音参数
     */
    stopVoice(args) {
        // 实现停止语音的逻辑
        return this.callApi('stopVoice', args)
    }

    /**
     * 语音播放结束
     * @param {Object} args - 语音播放结束参数
     */
    onVoicePlayEnd(args) {
        // 实现语音播放结束的逻辑
        return this.callApi('onVoicePlayEnd', args)
    }

    /**
     * 上传语音
     * @param {Object} args - 上传语音参数
     */
    uploadVoice(args) {
        // 实现上传语音的逻辑
        return this.callApi('uploadVoice', args)
    }

    /**
     * 下载语音
     * @param {Object} args - 下载语音参数
     */
    downloadVoice(args) {
        // 实现下载语音的逻辑
        return this.callApi('downloadVoice', args)
    }

    /**
     * 选择图片
     * @param {Object} args - 选择图片参数
     * @param {number} args.count - 选择的图片数量
     */
    chooseImage(args) {
        // 实现选择图片的逻辑
        return this.callApi('chooseImage', args)
    }

    /**
     * 预览图片
     * @param {Object} args - 预览图片的参数
     * @param {Array<string>} args.urls - 需要预览的图片链接数组
     * @param {string} [args.current] - 当前显示的图片链接
     */
    previewImage(args) {
        // 实现预览图片的逻辑
        return this.callApi('previewImage', args)
    }

    /**
     * 上传图片
     * @param {Object} args - 上传图片参数
     */
    uploadImage(args) {
        // 实现上传图片的逻辑
        return this.callApi('uploadImage', args)
    }

    /**
     * 下载图片
     * @param {Object} args - 下载图片参数
     */
    downloadImage(args) {
        // 实现下载图片的逻辑
        return this.callApi('downloadImage', args)
    }

    /**
     * 翻译语音
     * @param {Object} args - 翻译语音参数
     */
    translateVoice(args) {
        // 实现翻译语音的逻辑
        return this.callApi('translateVoice', args)
    }

    /**
     * 获取网络类型
     * @param {Object} args - 获取网络类型参数
     */
    getNetworkType(args) {
        // 实现获取网络类型的逻辑
        return this.callApi('getNetworkType', args)
    }

    /**
     * 打开位置
     * @param {Object} args - 打开位置参数
     * @param {string} args.name - 位置名称
     * @param {string} args.address - 位置地址
     * @param {number} args.latitude - 纬度
     * @param {number} args.longitude - 经度
     */
    openLocation(args) {
        // 实现打开位置的逻辑
        return this.callApi('openLocation', args)
    }

    /**
     * 获取位置
     * @param {Object} args - 获取位置参数
     */
    getLocation(args) {
        // 实现获取位置的逻辑
        return this.callApi('getLocation', args)
    }

    /**
     * 隐藏选项菜单
     * @param {Object} args - 隐藏选项菜单参数
     */
    hideOptionMenu(args) {
        // 实现隐藏选项菜单的逻辑
        return this.callApi('hideOptionMenu', args)
    }

    /**
     * 显示选项菜单
     * @param {Object} args - 显示选项菜单参数
     */
    showOptionMenu(args) {
        // 实现显示选项菜单的逻辑
        return this.callApi('showOptionMenu', args)
    }

    /**
     * 隐藏菜单项
     * @param {Object} args - 隐藏菜单项参数
     * @param {Array<string>} args.menuList - 需要隐藏的菜单项列表
     */
    hideMenuItems(args) {
        // 实现隐藏菜单项的逻辑
        return this.callApi('hideMenuItems', args)
    }

    /**
     * 显示菜单项
     * @param {Object} args - 显示菜单项参数
     * @param {Array<string>} args.menuList - 需要显示的菜单项列表
     */
    showMenuItems(args) {
        // 实现显示菜单项的逻辑
    }

    /**
     * 隐藏所有非基础菜单项
     * @param {Object} args - 隐藏菜单项参数
     */
    hideAllNonBaseMenuItem(args) {
        // 实现隐藏所有非基础菜单项的逻辑
        return this.callApi('hideAllNonBaseMenuItem', args)
    }

    /**
     * 显示所有非基础菜单项
     * @param {Object} args - 显示菜单项参数
     */
    showAllNonBaseMenuItem(args) {
        // 实现显示所有非基础菜单项的逻辑   
        return this.callApi('showAllNonBaseMenuItem', args)
    }

    /**
     * 关闭窗口
     * @param {Object} args - 关闭窗口参数
     */
    closeWindow(args) {
        // 实现关闭窗口的逻辑
        return this.callApi('closeWindow', args)

    }

    /**
     * 扫描二维码
     * @param {Object} args - 扫描二维码参数
     */
    scanQRCode(args) {
        // 实现扫描二维码的逻辑
        return this.callApi('scanQRCode', args)
    }

    /**
     * 打开商品详情页
     * @param {Object} args - 打开商品详情页参数
     * @param {string} args.productId - 商品 ID
     */
    openProductSpecificView(args) {
        // 实现打开商品详情页的逻辑
        return this.callApi('openProductSpecificView', args)
    }

    /**
     * 添加卡片
     * @param {Object} args - 添加卡片参数
     * @param {Array<Object>} args.cardList - 卡片列表
     */
    addCard(args) {
        // 实现添加卡片的逻辑
        return this.callApi('addCard', args)

    }

    /**
     * 选择卡片
     * @param {Object} args - 选择卡片参数
     */
    chooseCard(args) {
        // 实现选择卡片的逻辑
        return this.callApi('chooseCard', args)
    }

    /**
     * 打开卡片
     * @param {Object} args - 打开卡片参数
     */
    openCard(args) {
        // 实现打开卡片的逻辑
        return this.callApi('openCard', args)
    }


}
WeChatSDK.setAppId('wxe5780c4c488f735c')
export default WeChatSDK

